package main

import (
	"net/http"
	"os"
	"strconv"
	"sync"
	"time"

	jsoniter "github.com/json-iterator/go"

	"github.com/gin-gonic/gin"
)

func init() {
	// data := `{"layers":[{"id":"layer1","type":"image","name":"示例图片2","src":"http://192.168.31.249:8080/images/jpg/2","x":0,"y":0,"width":320,"height":320,"rotate":0,"isEditable":true},{"id":"layer2","type":"image","name":"示例图片2","src":"http://192.168.31.249:8080/images/png/1","x":0,"y":0,"width":640,"height":640,"rotate":0,"isEditable":true},{"id":"text1","type":"text","content":"示例文本","name":"示例文本","x":200,"y":200,"fontSize":20,"color":"#000000","fontFamily":"Arial","width":100,"height":30,"rotate":0,"isEditable":false}],"width":640,"height":640}`
	// var canvasConfig CanvasConfig
	// err := jsoniter.UnmarshalFromString(data, &canvasConfig)
	// if err != nil {
	// 	fmt.Println(err)
	// }
}

// Response 通用返回结构
type Response struct {
	Code    int         `json:"code"`
	Message string      `json:"message"`
	Data    interface{} `json:"data,omitempty"`
}

// Layer 图层结构
type Layer struct {
	ID          string `json:"id"`
	Type        string `json:"type"`
	Name        string `json:"name"`
	Src         string `json:"src,omitempty"`
	Content     string `json:"content,omitempty"`
	X           int    `json:"x"`
	Y           int    `json:"y"`
	Width       int    `json:"width"`
	Height      int    `json:"height"`
	Rotate      int    `json:"rotate"`
	IsEditable  bool   `json:"isEditable"`
	ZIndex      int    `json:"zIndex"`
	FontSize    int    `json:"fontSize,omitempty"`
	Color       string `json:"color,omitempty"`
	AspectRatio int    `json:"aspectRatio,omitempty"`
	FontFamily  string `json:"fontFamily,omitempty"`
}

// CanvasConfig 画布配置结构
type CanvasConfig struct {
	Layers                []Layer `json:"layers"`
	SelectedLayer         *Layer  `json:"selectedLayer"`
	OffsetX               int     `json:"offsetX"`
	OffsetY               int     `json:"offsetY"`
	Width                 int     `json:"width"`
	Height                int     `json:"height"`
	WindowWidth           int     `json:"windowWidth"`
	WindowHeight          int     `json:"windowHeight"`
	CanvasHeight          int     `json:"canvasHeight"`
	PixelRatio            int     `json:"pixelRatio"`
	Zoom                  int     `json:"zoom"`
	InitialDistance       int     `json:"initialDistance"`
	InitialDistanceWidth  int     `json:"initialDistanceWidth"`
	InitialDistanceHeight int     `json:"initialDistanceHeight"`
}

type reqLayersUpdate struct {
	ID     string       `json:"id"`
	Config CanvasConfig `json:"data"`
}

// Success 成功返回
func Success(data interface{}) Response {
	return Response{
		Code:    0,
		Message: "success",
		Data:    data,
	}
}

// Error 错误返回
func Error(code int, message string) Response {
	return Response{
		Code:    code,
		Message: message,
	}
}

func main() {
	r := gin.Default()
	// 初始化sync.Map
	var m sync.Map
	var json = jsoniter.Config{
		EscapeHTML:                    true,
		SortMapKeys:                   false,
		ValidateJsonRawMessage:        false,
		ObjectFieldMustBeSimpleString: false,
	}.Froze()

	r.POST("/layers/update", func(c *gin.Context) {
		// 直接定义一个请求数据格式，并赋值给data
		var data reqLayersUpdate
		body, _ := c.GetRawData()
		// 把json的data转换成CanvasConfig格式
		err := json.Unmarshal(body, &data)
		if err != nil {
			c.JSON(http.StatusOK, Error(500, "Invalid JSON data"+err.Error()+string(body)))
			return
		}
		if data.ID == "" {
			data.ID = strconv.FormatInt(time.Now().UnixNano(), 10)
		}
		// 存储到内存里
		m.Store(data.ID, data.Config)
		c.JSON(http.StatusOK, Success(data.ID))
	})

	// 定义 /layers/single 路由
	r.GET("/layers/single", func(c *gin.Context) {
		// 获取查询参数 id
		id := c.Query("id")

		// 如果没有提供 id 参数，返回错误
		if id == "" {
			c.JSON(http.StatusBadRequest, Error(400, "缺少必需的参数: id"))
			return
		}
		canvasConfig, ok := m.Load(id)
		if !ok {
			c.JSON(http.StatusOK, Error(500, "未找到该id"))
			return
		}
		// 返回成功响应
		c.JSON(http.StatusOK, Success(canvasConfig))
	})

	// get /images/:id 获取对应的图片
	r.GET("/images/:type/:id", func(c *gin.Context) {
		t := c.Param("type")
		id := c.Param("id")
		path := "/app/images/" + id + "." + t
		// 检查文件是否存在
		if _, err := os.Stat(path); os.IsNotExist(err) {
			// 设置path为main文件当前目录下的images
			path = "./images/" + id + "." + t
		}
		c.File(path)
	})

	r.Static("/static", "./images")

	r.POST("/images/upload", func(c *gin.Context) {
		file, _ := c.FormFile("file")
		// 文件名称用时间戳
		fileName := strconv.FormatInt(time.Now().UnixNano(), 10)
		c.SaveUploadedFile(file, "./images/"+fileName)
		c.JSON(http.StatusOK, Success(fileName))
	})
	r.Run(":8090")
}
